import * as ol from '../openLayer'
import WKT from 'ol/format/WKT'
import { getVectorContext } from 'ol/render.js'
import { getDistance } from 'ol/sphere.js'
import { PlaybarControl } from './play'
import { defaultConfig, coordinatesTypeArr } from './config'
import { deepAssign } from '@/utils/tools/deepAssign'
import { LineString } from 'ol/geom'
/**
 * 轨迹类
 */
export default class OlMapTrajectory {
  constructor (_map, _config) {
    this.map = _map
    this.options = deepAssign(defaultConfig, _config) //  配置项
    this.coordinatesType = coordinatesTypeArr.indexOf(this.options.coordinatesType) > -1 ? this.options.coordinatesType : defaultConfig.coordinatesType
    this.line = null // 直线
    this.lineFeature = null // 直线feature
    this.startMarker = null // 开始点位
    this.endMarker = null // 结束点位
    this.stopMakers = [] // 经停点
    this.routeStyle = null // 轨迹样式
    this.movePoint = null // 移动点
    this.movePointMarker = null //  移动点feature
    this.moveFeature = null // 移动feature
    this.lastTime = null //  最后一次移动时间
    this.animating = false // 是否正在移动，false-> 停止 true-> 移动
    this.trajectoryLayer = null //  openlayer 对象
    this.speed = this.options.speed //  移动速度
    this.distance = 0 // 已经移动的距离
    this.currentIndex = 0 //  当前坐标点下标
    this.lineAllLength = 0 //  轨迹总长度
    this.lineSegmentLength = [] // 线段直接的距离
    this.vectorContext = null // canvas 上下文
    this.tolerance = this.options.tolerance < 10 ? 10 : this.options.tolerance // 容差，最小为10
    this.imageAngle = this.options.imageAngle //  图片自身旋转角度
    this.coordinates = null//  点位信息
    if (this.options.coordinates.length > 1) {
      this.drwaRoute() //  绘制线条
      this.setRouteStyle() //  设置轨迹样式
      this.initMoveFeature() //  初始化移动moveFeature
      this.lineAllLength = this.getLineAllLength() //  获取线条总长度

      this.playbarControl = new PlaybarControl(this.map, _config, (e, pos) => { //  添加播放停止动画控制器
        if (pos === 100) { // 在尾端
          this.movePoint.setCoordinates(this.coordinates[0]) // 设置移动点当前位置
          this.movePointMarker.setGeometry(this.movePoint)
          this.distance = 0
          this.currentIndex = 0
          // this.redrawMovePoing(this.options.coordinates[0], this.options.coordinates) // 设置移动点到一个点位
        }
        this.setAnimation(e)
      }, (e) => {
        this.setAnimationSpeed(e)
      })
      this.map.addControl(this.playbarControl)
    }
  }

  /**
   * 重新绘制移动点位置和样式
   */
  redrawMovePoing (currentCoordinate, coordinates, vectorContext) {
    this.movePoint.setCoordinates(currentCoordinate) // 设置移动点当前位置
    // console.log('this.currentIndex=', this.currentIndex, this.getRotation(coordinates[this.currentIndex], coordinates[this.currentIndex + 1]))
    let rotation = this.getRotation(coordinates[this.currentIndex], coordinates[this.currentIndex + 1])
    if (rotation > 3) {
      rotation = rotation - this.imageAngle
    }
    let movePointStyle = new ol.Style({
      image: new ol.Icon({
        src: this.options.navStyle.url,
        scale: this.options.navStyle.scale,
        rotateWithView: false,
        rotation: rotation

      })
    })
    this.vectorContext.setStyle(movePointStyle) //  移动时重新计算线路角度
    this.vectorContext.drawGeometry(this.movePoint)
  }

  /**
 * 得到总线路长度
 * @returns
 */
  getLineAllLength () {
    let coordinates = this.coordinates
    let length = 0
    for (let i = 0; i < coordinates.length - 1; i++) {
      // console.log(coordinates[i], i)
      length = length + this.formatLength(coordinates[i], coordinates[i + 1])
      this.lineSegmentLength.push(parseInt(length))
    }
    // console.log('this.lineSegmentLength', this.lineSegmentLength)
    return length
  }

  /**
   * 设置动画的速度
   * @param {*} e
   */
  setAnimationSpeed (e) {
    this.speed = e * this.options.speed
    // this.initMoveFeature()
  }

  /**
   * 开启或者停止动画
   * @param {*} e
   */
  setAnimation (e) {
    // console.log('e', e)
    this.animating = e
    if (this.animating) {
      this.startAnimation()
    } else {
      this.stopAnimation()
    }
  }
  /**
   * 开始动画
   */

  startAnimation () {
    console.log('开始移动')
    this.animating = true
    this.lastTime = new Date().getTime() /** 开始时的时间 */
    this.trajectoryLayer.on('postrender', this.moveFeature)
    // hide geoMarker and trigger map render through change event
    this.movePointMarker.setGeometry(null)
  }

  /**
 * 停止动画
 */
  stopAnimation () {
    this.animating = false

    // Keep marker at current animation position
    this.movePointMarker.setGeometry(this.movePoint)
    this.trajectoryLayer.un('postrender', this.moveFeature)
  }

  /**
 * 获取线段长度
 * @param {*} line
 * @returns
 */
  formatLength (sourcePoint, targetPoint) {
    const length = getDistance(sourcePoint, targetPoint)
    let output
    if (length > 1000) {
      output = Math.round((length / 1000) * 100) / 100 + ' km'
    } else {
      output = Math.round(length * 100) / 100 + ' m'
    }
    return getDistance(sourcePoint, targetPoint)
  };
  /**
  * 根据坐标获取角度数，以正上方为0度作为参照
  * @param  sourcePoint 源点
  * @param  targetPoint 目标点
  */

  getRotation (sourcePoint, targetPoint) {
    // console.log('getRotation', this.currentIndex)
    if (this.options.angleConfig.hasDirection) { // 数据自带方晓角
      return this.options.coordinates[this.currentIndex][this.options.angleConfig.direction]
    } else { //  不带，自己计算
      try {
        return -Math.atan2(targetPoint[1] - sourcePoint[1], targetPoint[0] - sourcePoint[0]) + this.imageAngle //  计算导航图标旋转角度
      } catch (error) {
        console.log(error, sourcePoint, targetPoint)
      }
    }
  }

  /**
   * 初始化移动
   */
  initMoveFeature () {
    if (this.moveFeature) {
      // console.log('已存在', this.moveFeature)
    } else {
      let moveLength = 0
      let preCoordinate = this.coordinates[0]

      this.moveFeature = (e) => {
        // console.log('moveFeaturee=', e)
        // console.log('getEventPixel', this.map.getCoordinateFromPixel(e.inversePixelTransform))
        this.vectorContext = getVectorContext(e) // //HTML5 Canvas context，ol.render.canvas.Immediate的对象
        const speed = parseInt(this.speed)
        let frameState = e.frameState // freme 的状态
        const time = frameState.time
        const elapsedTime = time - this.lastTime
        this.lastTime = time
        if (this.distance === 0) {
          preCoordinate = this.coordinates[0]
          moveLength = 0
          this.lastTime = new Date().getTime()
        }
        let index = Math.round(speed * elapsedTime / 1000)
        // console.log('时间(s)', elapsedTime)
        // console.log('index=', index,speed * elapsedTime / 1000)
        // console.log('frameStateindex=', frameState.index)
        this.distance = (this.distance + (speed * elapsedTime) / 1e6) % 2

        // console.log('this.currentIndex=', this.currentIndex)
        // console.log('distance', this.distance)

        const currentCoordinate = this.line.getCoordinateAt(
          this.distance > 1 ? 2 - this.distance : this.distance
        )
        moveLength = moveLength + this.formatLength(preCoordinate, currentCoordinate) // 计算移动过的距离
        preCoordinate = currentCoordinate //  缓存上一个定位点
        // console.log('moveLength=', currentCoordinate, moveLength)
        // console.log('moveLength=', moveLength, this.lineSegmentLength.indexOf(moveLength))

        let progressWidth = (moveLength / this.lineAllLength) * 100 //  计算计算进度条的位置
        // console.log('progressWidth=', progressWidth)
        this.playbarControl.setProgressEleWidth(progressWidth) //  设置进度条的位置
        this.getCurrentIndex(moveLength, this.coordinates) // 计算移动点在坐标数组里的下标
        // console.log('this.currentIndex=', this.currentIndex, this.options.coordinates[this.currentIndex].speed)
        this.playbarControl.setSeedTip(this.options.coordinates[this.currentIndex].speed)
        this.redrawMovePoing(currentCoordinate, this.coordinates) // 从新绘制移动点的位置
        this.map.render() // 继续动画效果
        if (this.distance > 1) {
          this.stopAnimation()
        }
      }
    }
  }

  /**
   * 计算当前坐标点下标,
   * moveLength
   */
  getCurrentIndex (moveLength, coordinates) {
    let filtCoordinate = this.lineSegmentLength.filter(item => {
      let tempMoveLength = parseInt(moveLength)
      let tempItem
      // console.log(tempMoveLength, item)
      if (tempMoveLength > item - this.tolerance && tempMoveLength < item + this.tolerance) {
        tempItem = item
      }
      return tempItem
    })
    // console.log('filtCoordinate=', filtCoordinate)
    if (filtCoordinate.length > 0) {
      this.currentIndex = this.lineSegmentLength.indexOf(filtCoordinate[0])
      // console.log('this.currentIndex=', this.currentIndex)
    }
    if (this.currentIndex >= coordinates.length) {
      this.currentIndex = coordinates.length - 1
    }
  }

  /**
   * 道路轨迹
   */
  drwaRoute () {
    switch (this.coordinatesType) {
      case 'WKT':
        this.coordinates = this.options.coordinates.map(item => new WKT().readGeometry(item.point).getCoordinates())
        break
      case 'point':
        this.coordinates = this.options.coordinates.map(item => item.point)
        break
      default:
        this.coordinates = this.options.coordinates.map(item => new WKT().readGeometry(item.point).getCoordinates())
        break
    }
    console.log('pointsArr=', this.coordinates)
    // let pointsArr = this.options.coordinates.map(item => new WKT().readGeometry(item.point))
    if (this.coordinates && this.coordinates.length > 0) {
      this.line = new LineString(this.coordinates) //  直线
      // console.log('line all Coordinates', this.line.getCoordinates())
      // 线路所有坐标点坐标
      // let coordinates = this.options.coordinates
      this.lineFeature = new ol.Feature({ //  直线线路
        type: 'line',
        geometry: this.line
      })
      this.startMarker = new ol.Feature({ //  开始点位
        type: 'icon',
        geometry: new ol.Point(this.line.getFirstCoordinate()),
        properties: this.options.coordinates[0]
      })
      this.endMarker = new ol.Feature({ //  结束点位
        type: 'icon',
        geometry: new ol.Point(this.line.getLastCoordinate()),
        properties: this.options.coordinates[this.coordinates.length - 1]
      })
      /**
     * 经停点
     */

      for (let i = 1; i < this.coordinates.length - 1; i++) {
        let s = new ol.Feature({
          type: 'stop',
          geometry: new ol.Point(this.coordinates[i]),
          properties: this.options.coordinates[i]
        })
        // console.log('s', s)
        this.stopMakers.push(s)
      }

      this.movePoint = this.startMarker.getGeometry().clone() // 移动点
      // console.log('this.movePoint', this.startMarker, this.endMarker)
      this.movePointMarker = new ol.Feature({ //  移动点feature,初始化时在第一个开始点
        type: 'geoMarker',
        geometry: this.movePoint
      })
      // console.log(' this.movePointMarker', this.movePointMarker, this.startMarker)

      let routeFeature = [...[this.lineFeature, this.movePointMarker, this.startMarker, this.endMarker], ...this.stopMakers]
      // let routeFeature = [this.movePointMarker]
      this.trajectoryLayer = new ol.VectorLayer({ // 添加图层
        source: new ol.VectorSource({
          features: routeFeature,
          
        }),
        style: (feature) => {
          return this.routeStyle[feature.get('type')]
        },
        className: 'TrajectoryLayer',
        properties: this.options.layerProperties

      })

      this.map.addLayer(this.trajectoryLayer)
    }
  }

  /**
   * 设置轨迹线路样式
   */
  setRouteStyle () {
    let coordinates = this.coordinates
    let sourcePoint = coordinates[this.currentIndex]
    let targetPoint = coordinates[this.currentIndex + 1]

    this.routeStyle = { // 定义线路样式
      line: new ol.Style({
        stroke: new ol.Stroke({
          width: this.options.lineStyle.width,
          color: this.options.lineStyle.color
        })
      }),

      geoMarker: new ol.Style({
        image: new ol.Icon({
          src: this.options.navStyle.url,
          scale: this.options.navStyle.scale,
          rotateWithView: false,
          rotation: this.getRotation(sourcePoint, targetPoint)
          // rotation: this.options.coordinates[0].direction

        })

      }),
      icon: new ol.Style({
        image: new ol.CircleStyle({
          radius: this.options.iconStyle.radius - 2,
          fill: new ol.Fill({
            // width: this.options.routeStyle.width,
            color: this.options.iconStyle.color
          }),
          stroke: new ol.Stroke({
            width: (this.options.iconStyle.radius - 2) / 2,
            color: this.options.iconStyle.color
          })
        })
      }),
      stop: new ol.Style({
        image: new ol.CircleStyle({
          radius: this.options.stopStyle.radius - 2,
          fill: new ol.Fill({
            // width: this.options.routeStyle.width,
            color: this.options.stopStyle.color
          }),
          stroke: new ol.Stroke({
            width: (this.options.stopStyle.radius - 2) / 2,
            color: this.options.stopStyle.color
          })
        })
      })
    }
  }

  updateTrajectory (_map, _config) {
    this.map = _map
    this.options = deepAssign(defaultConfig, _config) //  配置项
  }
}
